package com.sntk.organauthomanager.query;

import com.sntk.organauthomanager.application.dto.OperatorInfo;
import com.sntk.organauthomanager.application.dto.ResourceDTO;
import com.sntk.organauthomanager.application.dto.ResourceVO;
import com.sntk.organauthomanager.application.mapper.ResourceMapper;
import com.sntk.organauthomanager.infrastructure.db.entity.*;
import com.sntk.organauthomanager.infrastructure.db.repository.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName: ResourceQuery
 * @author: wgchao
 * @createTime: 2020/7/21 4:55 PM
 * @Description: TODO
 */
@Service
@Transactional(readOnly = true)
public class ResourceQuery {
    @Autowired
    private ResourceDBRepository resourceDBRepository;
    @Autowired
    private RoleResourceDBRepository roleResourceDBRepository;
    @Autowired
    private UserRoleDBRepository userRoleDBRepository;
    @Autowired
    private UserDBRepository userDBRepository;
    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private UserResourceDBRepository userResourceDBRepository;

    public ResourceDTO searchResource(String mark){
        ResourceEntity resourceEntity = resourceDBRepository.findFirstByMarkAndDelFalse(mark);
        if(resourceEntity == null){
            return null;
        }
        return resourceMapper.transformToDTO(resourceEntity);
    }


    /**
     * 查询全部资源树
     * @return
     */
    public List<ResourceVO> searchResourcesWithTree(){
        List<ResourceEntity> resourceEntities = resourceDBRepository.findAllByDelIsFalseAndParentResourceIsNull();
        if(resourceEntities==null || resourceEntities.isEmpty()) {
            return null;
        }
        List<ResourceVO> resourceVOS = resourceEntities.stream().map(resourceEntity1 -> {
            ResourceVO resourceVO = resourceMapper.transformToVO(resourceEntity1);
            List<ResourceVO> childs = searchChildResources(resourceEntity1);
            resourceVO.setChilds(childs);
            return resourceVO;
        }).collect(Collectors.toList());
        return resourceVOS;
    }

    /**
     * 查询下级资源树
     * @param resourceEntity
     * @return
     */
    public List<ResourceVO> searchChildResources(ResourceEntity resourceEntity){
        List<ResourceEntity> resourceEntities = resourceDBRepository.findAllByParentResourceAndDelIsFalse(resourceEntity.getMark());
        if(resourceEntities==null || resourceEntities.isEmpty()) {
            return null;
        }
        List<ResourceVO> resourceVOS = resourceEntities.stream().map(resourceEntity1 -> {
            ResourceVO resourceVO = resourceMapper.transformToVO(resourceEntity1);
            List<ResourceVO> childs = searchChildResources(resourceEntity1);
            resourceVO.setChilds(childs);
            return resourceVO;
        }).collect(Collectors.toList());
        return resourceVOS;
    }


    /**
     * 查询某项目下资源树
     * @param proMark
     * @return
     */
    public ResourceVO searchResourcesOfProWithTree(String proMark){
        ResourceEntity resourceEntity = resourceDBRepository.findAllByMarkAndDelIsFalseAndParentResourceIsNull(proMark);
        if(resourceEntity == null) {
            return null;
        }
        ResourceVO resourceVO = resourceMapper.transformToVO(resourceEntity);
        List<ResourceVO> childs = searchChildResources(resourceEntity);
        resourceVO.setChilds(childs);
        return resourceVO;
    }


    /**
     * 查询角色可用资源
     * @return
     */
    public List<String> searchResourcesOfRole(String roleCode, String institutionNumber, boolean child){
        //查询角色资源
        List<RoleResourceEntity> roleResources = roleResourceDBRepository.findAllByRoleCodeAndInstitutionNumber(roleCode, institutionNumber);
        if(ObjectUtils.isEmpty(roleResources)){
            return null;
        }
        if (child){
            List<String> rr = roleResources.stream().map(roleResourceEntity -> roleResourceEntity.getResourceMark())
                    .collect(Collectors.toList());

            Set<String> rrSet = new HashSet<>(rr);
            return new ArrayList<>(rrSet);
        }else {
            List<String> rr = roleResources.stream().filter(roleResourceEntity -> {
                //获取最低级菜单（没有子级）
                List<ResourceEntity> resourceEntities = resourceDBRepository
                        .findAllByParentResourceAndDelIsFalse(roleResourceEntity.getResourceMark());
                if(ObjectUtils.isEmpty(resourceEntities)){
                    return true;
                }
                return false;
            }).map(roleResourceEntity -> roleResourceEntity.getResourceMark())
                    .collect(Collectors.toList());

            Set<String> rrSet = new HashSet<>(rr);
            return new ArrayList<>(rrSet);
        }

    }


    /**
     * 查询用户可用资源
     * @param operatorInfo
     * @return
     */
    public List<String> searchResourcesOfUser(OperatorInfo operatorInfo){
        if("admin".equals(operatorInfo.getOperator())){//admin用户 拥有所有资源权限
            //查询顶级资源
            List<ResourceEntity> resourceEntities = resourceDBRepository.
                    findAllByDelIsFalse();
            if(resourceEntities==null || resourceEntities.isEmpty()){
                return null;
            }
            List<String> resourceVOS = resourceEntities.stream().map(resourceEntity1 -> {
                return resourceEntity1.getMark();
            }).collect(Collectors.toList());
            return resourceVOS;
        }else {
            UserEntity userEntity = userDBRepository.findFirstByUnameAndDelFalse(operatorInfo.getOperator());
            if(userEntity == null || userEntity.getDisabled()){
                //用户已删除或禁用
                return null;
            }

            Set<String> resourceSet = new HashSet<>();

            //查询用户拥有角色权限
            List<UserRoleEntity> userRoleEntities = userRoleDBRepository.
                    findAllByUnameAndInstitutionNumber(operatorInfo.getOperator(), operatorInfo.getInstitutionNumber());
            if(!ObjectUtils.isEmpty(userRoleEntities)){
                for(UserRoleEntity userRoleEntity : userRoleEntities){
                    List<String> urs = searchResourcesOfRole(userRoleEntity.getRoleCode(), userRoleEntity.getInstitutionNumber(), true);
                    if(urs != null){
                        resourceSet.addAll(urs);
                    }
                }
            }

            //查询用户私有权限资源
            List<String> rmarks = searchResourcesOfUserOwn(operatorInfo.getOperator(), operatorInfo.getInstitutionNumber(), true);
            if(rmarks != null){
                resourceSet.addAll(rmarks);
            }

            return new ArrayList<>(resourceSet);
        }
    }


    /**
     * 查询用户私有资源
     * @param uname
     * @param institutionNumber
     * @return
     */
    public List<String> searchResourcesOfUserOwn(String uname, String institutionNumber, boolean child) {
        //查询用户私有权限资源
        List<UserResourceEntity> userResourceEntities = userResourceDBRepository.
                findAllByUnameAndInstitutionNumber(uname, institutionNumber);
        if(userResourceEntities==null || userResourceEntities.isEmpty()){
            return null;
        }
        if(child) {
            List<String> rmarks = userResourceEntities.stream().map(userResourceEntity -> {
                return userResourceEntity.getResourceMark();
            }).collect(Collectors.toList());
            return rmarks;
        }else {
            List<String> rmarks = userResourceEntities.stream().filter(roleResourceEntity -> {
                //获取最低级菜单（没有子级）
                List<ResourceEntity> resourceEntities = resourceDBRepository
                        .findAllByParentResourceAndDelIsFalse(roleResourceEntity.getResourceMark());
                if(ObjectUtils.isEmpty(resourceEntities)){
                    return true;
                }
                return false;
            }).map(userResourceEntity -> {
                return userResourceEntity.getResourceMark();
            }).collect(Collectors.toList());
            return rmarks;
        }
    }


}
